package gtgold;

import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.Field;
import javax.swing.*;

//import org.yaml.snakeyaml.Yaml;

/**
 * The main screen of the game that displays current game data information
 * 
 * @author jo, jen, isa
 */
public class MainScreen extends JPanel
{
	private static final long serialVersionUID = 1L;
	private GameManager manager;
	private JButton store, cont, rest, inventory, map;
	// Make sure to keep these names in sync
	private JLabel location, distanceTraveled, foodRemaining, pace, ration, health, date, moveStatus;
	private gifImagePanel movingBg;
	private final bgImagePanel stillBg;
	private JPanel attr;
	private Timer continueTimer;

	/**
	 * Create a new MainScreen JPanel
	 * 
	 * @param manager
	 *            parent GameManager to retrieve game data
	 */
	public MainScreen(final GameManager manager)
	{
		//Yaml yaml = new Yaml();
		
		
		this.manager = manager;
		setPreferredSize(OregonTrail.VGA);
		setLayout(new GridLayout(1, 1));

		// Main Still JPanel
		stillBg = new bgImagePanel("src/gtgold/img/OTbg01.jpg");
		stillBg.setLayout(new GridLayout(1, 1));

		// Animated JPanel
		movingBg = new gifImagePanel("src/gtgold/img/otrailbg.gif");
		movingBg.setLayout(new GridLayout(1, 1));

		// Attributes JPanel
		attr = new JPanel();
		attr.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		c.fill = GridBagConstraints.BOTH;

		/////////////////////////////////////////////////////
		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth = 5;

		c.weightx = 5;
		c.weighty = 1;
		attr.add(location = new JLabel(), c);

		c.gridy = 1;
		attr.add(distanceTraveled = new JLabel(), c);

		c.gridy = 2;
		attr.add(foodRemaining = new JLabel(), c);

		c.gridy = 3;
		attr.add(date = new JLabel(), c);
		
		/////////////////////////////////////////////////////
		c.gridx = 10;
		c.gridy = 0;
		attr.add(pace = new JLabel(), c);

		c.gridy = 1;
		attr.add(ration = new JLabel(), c);

		c.gridy = 2;
		attr.add(health = new JLabel(), c);		
		
		c.gridy = 3;
		attr.add(moveStatus = new JLabel(), c);
		/////////////////////////////////////////////////////
		
		c.gridwidth = 1;
		c.weightx = 1;
		for (int i = 5; i <= 13; i++)
			for (int j = 0; j < 2; j++)
			{
				c.gridx = j;
				c.gridy = i;
				JPanel spacing = new JPanel();
				spacing.setOpaque(false);
				attr.add(spacing, c);
			}

		/*
		 * //Use reflection to initialize labels. As long as this is kept in
		 * sync, there shouldn't be any exceptions String[] infoLabelNames =
		 * {"location", "distanceTraveled", "foodRemaining", "pace", "ration"};
		 * 
		 * for (int i = 0; i < 14; i++) // R1-R14 { if (i <
		 * infoLabelNames.length){
		 * 
		 * JLabel newLabel = new JLabel(); add(newLabel);
		 * 
		 * setField(infoLabelNames[i], newLabel); } else{ add(new JPanel());
		 * 
		 * }
		 * 
		 * for (int j = 0; j < 4; j++){ //padding between rows add(new
		 * JPanel()); } }
		 */

		c.gridy = 14;
		c.gridx = 0;
		c.weightx = 5;
		JPanel space = new JPanel();
		space.setOpaque(false);
		attr.add(space, c);
		cont = new JButton("Continue");
		cont.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent ae)
			{
				int previousDistanceTraved = gameData().distanceTraveled;
				manager.update();
				updateLabels();
				int currentDistanceTraveled = gameData().distanceTraveled;
				if (currentDistanceTraveled != previousDistanceTraved){
				// cont.setEnabled(false);
				// switches Bg to animated Bg & starts timer
				movingBg.add(attr);
				stillBg.add(movingBg);
				movingBg.setVisible(true);
				continueTimer.setRepeats(false);
				continueTimer.start();
				}
				// gray out shop button when necessary
				if (gameData().Location().isShop())
				{
					store.setEnabled(true);
				} else
				{
					store.setEnabled(false);
				}
			}
		});
		c.gridx = 2;
		attr.add(cont, c);

		rest = new JButton("Rest");
		rest.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent ae)
			{
				gameData().rest(1);
				manager.update();
				updateLabels();

			}
		});
		c.gridx = 3;
		attr.add(rest, c);

		store = new JButton("Visit Store");
		store.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent ae)
			{
				manager.openShopMenu();
				updateLabels(); // Make sure to update the amount of food after
								// shopping
			}
		});
		c.gridx = 4;
		attr.add(store, c);

		inventory = new JButton("Other Options");
		inventory.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent ae)
			{
				manager.openInventory();
				updateLabels();
			}
		});
		c.gridx = 5;
		attr.add(inventory, c);

		map = new JButton("Map");
		map.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent ae)
			{
				new GameMap(manager);
				updateLabels(); // Make sure to update the amount of food after
								// shopping
			}
		});
		c.gridx = 6;
		attr.add(map, c);

		// Stops animated Bg and reverts to still Bg
		continueTimer = new Timer(2000, new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				stillBg.remove(movingBg);
				stillBg.add(attr);
				stillBg.setVisible(true);
				// cont.setEnabled(true);
			}
		});

		attr.setOpaque(false);
		stillBg.add(attr);
		add(stillBg);
		updateLabels();
		setVisible(true);

	}

	public void updateLabels()
	{

		if (gameData().distanceLeft <= 0)
		{
			location.setText("  Location: " + gameData().destination.name);
		} else
		{
			location.setText("  Location: " + gameData().distanceLeft
					+ " miles from " + gameData().destination.name);
		}

		distanceTraveled.setText("  Traveled: " + gameData().distanceTraveled
				+ " miles");
		foodRemaining.setText("  Food: " + gameData().inventory.get(Item.FOOD)
				+ " lbs");
		date.setText("  Day: " + gameData().daysElapsed);
		
		pace.setText("Pace: " + gameData().pace.toString().toLowerCase());
		ration.setText("Rations: " + gameData().ration.toString().toLowerCase());
		moveStatus.setText("Status: " + gameData().moveStatus);	
		
		//For health status, find least healthy living person
		Person which = null;
		for(Person p : gameData().party){
			if (!p.alive()) {continue;}
			if (which == null || p.health() < which.health()) {which = p;}
		}
		
		health.setText("Health: " + which.status());
		
	}

	private GameData gameData()
	{
		return manager.data;
	}

	@SuppressWarnings("unused")
	private void setField(String name, Object val)
	{
		try
		{
			// We have to use declared field because otherwise only public
			// attributes are accessible
			MainScreen.class.getDeclaredField(name).set(this, val);
		} catch (IllegalArgumentException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// For testing
	@SuppressWarnings("unused")
	private void printFields()
	{
		for (Field f : MainScreen.class.getDeclaredFields())
		{
			try
			{
				print(f.getType().getName() + '\t' + f.getName() + "\t = \t"
						+ f.get(this));
			} catch (IllegalArgumentException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private static void print(String s)
	{
		System.out.println(s);
	}

}
